package com.alibaba.mnnllm.api.openai.service

import android.Manifest
import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.os.Binder
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import com.alibaba.mnnllm.android.chat.ChatActivity
import com.alibaba.mnnllm.api.openai.service.ApiServiceCoordinator
import com.alibaba.mnnllm.api.openai.manager.ApiNotificationManager
import com.alibaba.mnnllm.api.openai.manager.CurrentModelManager
import timber.log.Timber

class OpenAIService : Service() {
    private val TAG = this::class.java.simpleName
    private lateinit var coordinator: ApiServiceCoordinator
    private var currentModelId: String? = null

    companion object {
        private var isServiceRunning = false
        private var serviceConnection: ServiceConnection? = null

        fun startService(context: Context, modelId: String? = null) {
            if (context !is ChatActivity) {
                Timber.tag("ServiceStartCondition").w("Invalid context. Not starting service.")
                return
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                if (ContextCompat.checkSelfPermission(
                        context,
                        Manifest.permission.POST_NOTIFICATIONS
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    Timber.tag("ServiceStartCondition").w("Notification permission not granted, cannot start foreground service")
                    return
                }
            }

            val serviceIntent = Intent(context, OpenAIService::class.java)
            //pass modelId toservice
            modelId?.let { serviceIntent.putExtra("modelId", it) }
            isServiceRunning = true
            try {
                context.startForegroundService(serviceIntent)
                Timber.tag("ServiceStartCondition").i("Foreground service started successfully")
            } catch (e: Exception) {
                Timber.tag("ServiceStartCondition").e(e, "Failed to start foreground service")
                isServiceRunning = false
                return
            }

            val connection = object : ServiceConnection {
                override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
                    val localBinder = binder as LocalBinder
                    localBinder.initialize()
                    serviceConnection = this
                }

                override fun onServiceDisconnected(name: ComponentName?) {
                    serviceConnection = null
                    isServiceRunning = false
                }
            }

            context.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)
            serviceConnection = connection
        }

        /** * releaseserviceresourceandstopservice * * @param context contextobject * @param force whetherforcestop，defaultasfalse*/
        fun releaseService(context: Context, force: Boolean = false) {
            val serviceIntent = Intent(context, OpenAIService::class.java)
            
            try {
                if (force) {
                    context.stopService(serviceIntent)
                    Timber.tag("ServiceRelease").w("Service stopped forcefully")
                } else {
                    if (context.stopService(serviceIntent)) {
                        Timber.tag("ServiceRelease").i("Service stopped gracefully")
                    } else {
                        Timber.tag("ServiceRelease").w("Service was not running")
                    }
                }
            } catch (e: Exception) {
                Timber.tag("ServiceRelease").e(e, "Failed to stop service")
                if (force) {
                    try {
                        context.stopService(serviceIntent)
                        Timber.tag("ServiceRelease").w("Retry force stop succeeded")
                    } catch (e: Exception) {
                        Timber.tag("ServiceRelease").e(e, "Force stop also failed")
                    }
                }
            }

            serviceConnection?.let { conn ->
                try {
                    context.unbindService(conn)
                    Timber.tag("ServiceRelease").i("Unbound successfully")
                } catch (e: Exception) {
                    Timber.tag("ServiceRelease").w(e, "Failed to unbind service")
                    if (force) {
                        try {
                            context.unbindService(conn)
                            Timber.tag("ServiceRelease").w("Force unbind succeeded")
                        } catch (e: Exception) {
                            Timber.tag("ServiceRelease").e(e, "Force unbind also failed")
                        }
                    }
                } finally {
                    serviceConnection = null
                }
            }

            isServiceRunning = false
            Timber.tag("ServiceLifecycle").i("OpenAIService resources released")
        }
    }



    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (!isServiceRunning) {
            Timber.tag("ServiceLifecycle").w("Service started illegally and will be stopped immediately.")
            stopSelf()
            return START_NOT_STICKY
        }
        
        //getpass modelId
        intent?.getStringExtra("modelId")?.let { modelId ->
            currentModelId = modelId
            CurrentModelManager.setCurrentModelId(modelId)
            Timber.tag(TAG).i("Service started with modelId: $modelId")
        }
        
        val notification = coordinator.getNotification()
        if (notification != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                startForeground(ApiNotificationManager.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
            } else {
                startForeground(ApiNotificationManager.NOTIFICATION_ID, notification)
            }
        }
        return START_NOT_STICKY
    }

    override fun onCreate() {
        super.onCreate()
        coordinator = ApiServiceCoordinator(this)
        coordinator.initialize()
    }




    

    override fun onDestroy() {
        Timber.tag(TAG).i("Service is being destroyed")
        cleanup()
        super.onDestroy()
    }

    override fun onBind(intent: Intent?): IBinder {
        Timber.tag(TAG).d("Service bound by client")
        return LocalBinder()
    }

    inner class LocalBinder : Binder() {
        fun getService(): OpenAIService = this@OpenAIService
        fun initialize() = this@OpenAIService.initializeWithSession()
    }


    /** * cleanupserviceresource * * includingstopforegroundserviceandcleanupcoordinatorresource*/
    private fun cleanup() {
        try {
            coordinator.cleanup()
            Timber.tag(TAG).d("Coordinator cleanup completed")
        } catch (e: Exception) {
            Timber.tag(TAG).e(e, "Failed to cleanup coordinator")
        }
        
        //clearglobalmodelID
        CurrentModelManager.clearCurrentModelId()

        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                stopForeground(STOP_FOREGROUND_REMOVE)
                Timber.tag(TAG).d("Foreground service stopped (API >= TIRAMISU)")
            } else {
                @Suppress("DEPRECATION")
                stopForeground(true)
                Timber.tag(TAG).d("Foreground service stopped (legacy API)")
            }
        } catch (e: Exception) {
            Timber.tag(TAG).e(e, "Failed to stop foreground service")
        } finally {
            Timber.tag(TAG).i("Service cleanup completed")
        }
    }


    fun initializeWithSession() {
        val success = coordinator.startServer()
        if (!success) {
            Timber.tag(TAG).w("Failed to start server through coordinator")
        }
    }

    fun updateNotification(contentTitle: String, contentText: String) {
        coordinator.updateNotification(contentTitle, contentText)
    }

    fun getServerPort(): Int? = coordinator.getServerPort()
    
    fun isServerRunning(): Boolean = coordinator.isServerRunning
    
    fun getCurrentModelId(): String? = currentModelId
}
